package com.moliku.insurance.process.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.moliku.insurance.common.constant.CompanyEnum;
import com.moliku.insurance.common.constant.InsureStatusEnum;
import com.moliku.insurance.common.constant.OrderEnum;
import com.moliku.insurance.common.constant.PolicyConfigKeyEnum;
import com.moliku.insurance.common.response.CommonInsureResult;
import com.moliku.insurance.common.util.XMLUtil;
import com.moliku.insurance.model.dto.CancelInsureDTO;
import com.moliku.insurance.model.dto.DownloadInsureDTO;
import com.moliku.insurance.model.dto.insure.InsureDTO;
import com.moliku.insurance.model.dto.insure.InsuredInfoDTO;
import com.moliku.insurance.model.entity.Order;
import com.moliku.insurance.model.entity.OrderDetail;
import com.moliku.insurance.model.entity.funde.*;
import com.moliku.insurance.process.mapper.BaseOrderMapper;
import com.moliku.insurance.process.service.ConfigService;
import com.moliku.insurance.process.strategy.PolicyStrategy;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 富德保险
 *
 * @author Mr.Liu
 * @since 2021/2/25
 */
@Slf4j
@AllArgsConstructor
@Service("FundeService")
public class FundeServiceImpl implements PolicyStrategy {

    /**
     * 投保地址
     */
//    private static final String SUBMIT_URL = "https://m-int.fundins.com/SL_ACCISP/MOBILE/third/doBusiness";

    /**
     * 退保地址
     */
//    private static final String CANCEL_URL = "https://m-int.fundins.com/SL_ACCISP/MOBILE/third/doEndor";

    /**
     * 下载地址
     */
//    private static final String DOWNLOAD_URL = "https://m-int.fundins.com/SL_ACCISP/MOBILE/third/downloadPcisPolicyPdf";

    /**
     * 投保成功的状态码
     */
    private static final String INSURED_SUCCESS_CODE = "100";
    /**
     * 重复投保的状态码
     */
    private static final String REPEAT_INSURED_SUCCESS_CODE = "102";
    /**
     * 退保成功的状态码
     */
    private static final String CANCEL_SUCCESS_CODE = "6";

    private final RestTemplate restTemplate;

    @Autowired
    private ConfigService configService;
    @Autowired
    private BaseOrderMapper baseOrderMapper;


    @Override
    public CommonInsureResult submitPolicy(InsureDTO request) {
        try {
            if (request.getOrder().getSerialNumber().length() > 20) {
                return CommonInsureResult.submitPolicyFail("投保失败：交易流水号长度不能超过20！");
            }
            //方案信息
            FundeProject fundeProject = new FundeProject();
//            fundeProject.setProjectCode(request.getOrder().getPlanCode());
            fundeProject.setProjectCode(request.getOrder().getProductCode());
            fundeProject.setProjectType("0010");
//            fundeProject.setProjectType(request.getOrder().getProjectType());

            //险种信息
            FundeRisk fundeRisk = new FundeRisk();
//            fundeRisk.setRiskCode(request.getOrder().getProductCode());
            fundeRisk.setRiskCode("1153");
            fundeRisk.setInsuranceBeginDate(request.getOrder().getStartTime());
            fundeRisk.setInsuranceEndDate(request.getOrder().getEndTime());
            //保额 不可以为空
            fundeRisk.setRiskSumInsured(new BigDecimal(40000.00));
            //保费
            fundeRisk.setRiskSumPremium(request.getOrder().getPremium());

            //投保人信息
            Relatedparty relatedparty = new Relatedparty();
            relatedparty.setAppType("2");
            relatedparty.setAppName(request.getPolicyHolder().getcName());
            relatedparty.setAppIdentifyType(getCardType(request.getPolicyHolder().getCardType()));
            relatedparty.setAppIdentifyNo(request.getPolicyHolder().getCardNo());
            relatedparty.setAppBirthday(request.getPolicyHolder().getBirthDay());
            relatedparty.setAppMobilePhone(request.getPolicyHolder().getMobile());
            relatedparty.setAppEmail(request.getPolicyHolder().getEmail());
            relatedparty.setAppBillRequire("03");
            relatedparty.setAppSex(request.getPolicyHolder().getSex());

            //被保人信息
            List<FundeListInsured> listInsuredList = new ArrayList<FundeListInsured>();
            for (InsuredInfoDTO infoDTO : request.getInsureds()) {
                FundeInsured fundeInsured = new FundeInsured();
                fundeInsured.setInsueredClientCName(infoDTO.getCName());
                fundeInsured.setInsueredBirthday(infoDTO.getBirthDay());
                fundeInsured.setInsueredAge(getInsuredAge(infoDTO.getBirthDay()));
                fundeInsured.setInsueredHomeTel(infoDTO.getMobile());
                fundeInsured.setInsueredEmail(infoDTO.getEmail());
                fundeInsured.setInsueredIdentifyType(getInsuredCardType(infoDTO.getCardType()));
                fundeInsured.setInsueredIdentifyNo(infoDTO.getCardNo());
                fundeInsured.setInsueredSex(infoDTO.getSex());
                FundeListInsured fundeListInsured = new FundeListInsured();
                fundeListInsured.setInsured(fundeInsured);
                listInsuredList.add(fundeListInsured);
            }

            RiskDynamic riskDynamic = new RiskDynamic();
            riskDynamic.setRiskDynamicFieldAC("中国境内");

            //投保信息
            FundeProduct fundeProduct = new FundeProduct();
            fundeProduct.setProject(fundeProject);
            fundeProduct.setRisk(fundeRisk);
            fundeProduct.setRelatedparty(relatedparty);
            fundeProduct.setListInsured(listInsuredList);
            fundeProduct.setRiskDynamic(riskDynamic);

            FundeProductList fundeProductList = new FundeProductList();
            fundeProductList.setProduct(fundeProduct);

            //请求体
            String userInfo = baseOrderMapper.selectByCompanyCode(request.getOrder().getChannel1Code());
            JSONObject object = JSONUtil.parseObj(JSONUtil.parseObj(userInfo).get("FUNDE"));
            FundeRequest fundeRequest = new FundeRequest();
            //查询账号密码
            String username = configService.getConfigValue(CompanyEnum.FUNDE, PolicyConfigKeyEnum.USERNAME);
            String password = configService.getConfigValue(CompanyEnum.FUNDE, PolicyConfigKeyEnum.PASSWORD);
            String partnerId = configService.getConfigValue(CompanyEnum.FUNDE, "partnerId");
            String tranCode = configService.getConfigValue(CompanyEnum.FUNDE, "tranCode");
            fundeRequest.setPartnerId(partnerId);
            fundeRequest.setTranCode(tranCode);
            fundeRequest.setUserCode(username);
            fundeRequest.setPassWord(password);
            fundeRequest.setOrderNo(request.getOrder().getSerialNumber());
            fundeRequest.setProductList(fundeProductList);

            //请求跟
            FundePackage fundePackage = new FundePackage();
            fundePackage.setRequest(fundeRequest);

            String strXml = XMLUtil.convertToXml(fundePackage);
            log.info("请求内容--{}", strXml);

            //发起请求
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("text/xml;charset=UTF-8"));
            HttpEntity<String> httpEntity = new HttpEntity<String>(strXml, headers);
            String submitUrl = configService.getConfigValue(CompanyEnum.FUNDE, PolicyConfigKeyEnum.SUBMIT_POLICY_URL);
            ResponseEntity<String> entity = restTemplate.postForEntity(submitUrl, httpEntity, String.class);
            log.info("响应：{}", entity.getBody());
            //判断响应格式是否是XML类型
            if (!XMLUtil.isXmlDocument(entity.getBody())) {
                return CommonInsureResult.submitPolicyFail();
            }
            //xml转json
            JSONObject jsonObject = JSONUtil.xmlToJson(entity.getBody());
            log.info("xml转json--{}", jsonObject.toString());
            //保存返回结果
            Order order = baseOrderMapper.selectById(request.getLocalOrderId());
            OrderDetail orderDetail = baseOrderMapper.selectDeatailByOrderId(order.getId());
            orderDetail.setInsureRsp(jsonObject.toString());
            baseOrderMapper.updateOrderDeatailByOrderId(orderDetail);
            String body = JSONUtil.parseObj(JSONUtil.parseObj(jsonObject.get("Package")).get("ProductList").toString()).get("Product").toString();
            String policyNo = "";
            String status = JSONUtil.parseObj(body).get("Status").toString();
            if (INSURED_SUCCESS_CODE.equals(status)) {
                //获取保单号
                policyNo = JSONUtil.parseObj(body).get("PolicyNo").toString();
                order.setPolicyNo(policyNo);
                order.setStatus(OrderEnum.CLOSED_NO_REFUND.getValue());
                baseOrderMapper.updateById(order);
                //获取保单状态
            } else if (REPEAT_INSURED_SUCCESS_CODE.equals(status)) {
                return CommonInsureResult.submitPolicyFail(InsureStatusEnum.INSURE_FAIL_5101);
            } else {
                String msg = JSONUtil.parseObj(body).get("ErrorMsg").toString();
                return CommonInsureResult.submitPolicyFail(msg);
            }
            return CommonInsureResult.submitPolicySuccess(policyNo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return CommonInsureResult.submitPolicyFail();
    }

    @Override
    public CommonInsureResult cancelPolicy(CancelInsureDTO request) {
        try {
            String username = configService.getConfigValue(CompanyEnum.FUNDE, PolicyConfigKeyEnum.USERNAME);
            String cancelUrl = configService.getConfigValue(CompanyEnum.FUNDE, PolicyConfigKeyEnum.CANCEL_POLICY_URL);
            String partnerId = configService.getConfigValue(CompanyEnum.FUNDE, "partnerId");
            String url = cancelUrl + "?partnerId=" + partnerId + "&policyNo=" + request.getPolicyNo() +
                    "&userCode=" + username + "&riskCode=" + "1153";
            log.info("退保地址--{}", url);
//            HttpHeaders httpHeaders = new HttpHeaders();
//            httpHeaders.add(HttpHeaders.CONTENT_TYPE, "text/xml;charset=UTF-8");
//            HttpEntity<String> httpEntity = new HttpEntity<String>(httpHeaders);
            ResponseEntity<String> cancelResponse = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
            log.info("退保返回--{}", cancelResponse.getBody());
            //判断响应格式是否是XML类型
            if (!XMLUtil.isXmlDocument(cancelResponse.getBody())) {
                return CommonInsureResult.cancelPolicyFail();
            }
            //xml转json
            JSONObject jsonObject = JSONUtil.xmlToJson(cancelResponse.getBody());
            log.info("xml转json--{}", jsonObject.toString());
            Order orderInfo = baseOrderMapper.selectByPolicyNo(request.getPolicyNo());
            OrderDetail orderDetail = baseOrderMapper.selectDeatailByOrderId(orderInfo.getId());
            orderDetail.setCancelPolicyRsp(jsonObject.toString());
            baseOrderMapper.updateOrderDeatailByOrderId(orderDetail);
            String body = JSONUtil.parseObj(JSONUtil.parseObj(jsonObject.get("Package")).get("ProductList").toString()).get("Product").toString();
            String status = JSONUtil.parseObj(body).isNull("UnderWriteInd") ? null : JSONUtil.parseObj(body).get("UnderWriteInd").toString();
            if (StringUtils.isEmpty(status)) {
                return CommonInsureResult.cancelPolicyFail();
            } else if (CANCEL_SUCCESS_CODE.equals(status)) {
                //退保成功
                orderInfo.setStatus(OrderEnum.CANCEL.getValue());
                baseOrderMapper.updateById(orderInfo);
            } else {
                return CommonInsureResult.cancelPolicyFail();
            }
            return CommonInsureResult.cancelPolicySuccess();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return CommonInsureResult.cancelPolicyFail();
    }

    @Override
    public CommonInsureResult downloadPolicy(DownloadInsureDTO downloadInsure) {
        try {
//            String url = DOWNLOAD_URL + "?OrderNo=" + downloadInsure.getSerialNo() + "&PolicyNo=" + downloadInsure.getPolicyNo() +
//                    "&AppName=" + downloadInsure.getAppName() + "&AppIdentifyType=" + downloadInsure.getAppIdentifyType() +
//                    "&AppIdentifyNo=" + downloadInsure.getAppIdentifyNo();
            String downloadUrl = configService.getConfigValue(CompanyEnum.FUNDE, PolicyConfigKeyEnum.DOWNLOAD_POLICY_URL);
            String url = downloadUrl + "?OrderNo=" + "2021030121233456a" + "&PolicyNo=" + downloadInsure.getPolicyNo() +
                    "&AppName=" + "张五" + "&AppIdentifyType=" + "99" +
                    "&AppIdentifyNo=" + "350102200010022815";

            log.info("下载地址--{}", url);
//            HttpHeaders httpHeaders = new HttpHeaders();
//            httpHeaders.add(HttpHeaders.CONTENT_TYPE, "text/xml;charset=UTF-8");
//            HttpEntity<String> httpEntity = new HttpEntity<String>(httpHeaders);
            ResponseEntity<String> downResponse = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
            log.info("下载响应--{}", downResponse.getBody());
            if (StringUtils.isEmpty(downResponse.getBody())) {
                return CommonInsureResult.downloadPolicyFail();
            }
            // TODO: 2021/3/20 需要返回byte 数组
            // return R.success("下载成功").data(downResponse.getBody());
            return CommonInsureResult.downloadPolicySuccess(new byte[]{});
        } catch (Exception e) {
            e.printStackTrace();
        }
        return CommonInsureResult.downloadPolicyFail();
    }

    /**
     * @Description: 返回 被保人年龄
     * @Author: yws
     * @Date: 2021/3/10 16:27
     */
    private static String getInsuredAge(String birthDate) throws Exception {
        //1、定义转换格式
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat formatterBirth = new SimpleDateFormat("yyyyMMdd");
        Date dateBirth = formatterBirth.parse(birthDate);
        Calendar calBegin = Calendar.getInstance();
        Calendar calEnd = Calendar.getInstance();
        calBegin.setTime(formatter.parse(formatter.format(dateBirth)));
        calEnd.setTime(formatter.parse(formatter.format(new Date())));
        int age = calEnd.get(Calendar.YEAR) - calBegin.get(Calendar.YEAR);
        return String.valueOf(age);
    }


    /**
     * @Description: 返回投保人身份证类型
     * @Param: cardType
     * @Return: String
     * @Author: yws
     * @Date: 2021/3/6 10:58
     */
    private static String getCardType(String cardType) {
        switch (cardType) {
            //组织机构代码
            case "72":
                return "1";
            //统一社会信用代码
            case "84":
                return "3";
            //注册号
            case "70":
                return "4";
            //其他
            case "99":
                return "99";
            //税务登记证
            default:
                return "2";
        }
    }

    /**
     * @Description: 返回被保人身份证类型
     * @Param: cardType
     * @Return: String
     * @Author: yws
     * @Date: 2021/3/6 10:58
     */
    private static String getInsuredCardType(String cardType) {
        switch (cardType) {
            //身份证号
            case "1":
                return "01";
            //护照
            case "3":
                return "02";
            //军人证
            case "4":
                return "03";
            //驾驶证
            case "5":
                return "04";
            //港澳台同胞证
            case "09":
                return "05";
            case "10":
                return "05";
            //居留证
            case "53":
                return "08";
            //港澳台居民居住证
            case "15":
                return "09";
            //其他
            case "99":
                return "99";
            //中国护照
            default:
                return "07";
        }
    }

}
